package com.tsj.model.controller;

import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author taoshujian
 * @version 1.0
 * @since 2025-10-22 09:16:21
 */
@RestController
@Tag(name = "文件下载")
@RequestMapping("/file")
public class FileController {

    @Operation(summary = "下载模板文件")
    @GetMapping("/download/template/excel")
    public ResponseEntity<byte[]> downloadTemplateExcel() {
        // 1. 定义模板文件路径（相对于resources目录）
        String templatePath = "static/templates/hero导入模板.xlsx";
        // 2. 定义下载时的文件名（浏览器显示的名称）
        String fileName = "excel导入模板.xlsx";
        try {
            // 3. 读取resources中的文件
            Resource resource = new ClassPathResource(templatePath);
            if (!resource.exists()) {
                // 文件不存在时返回404
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
            }

            // 4. 读取文件流
            try (InputStream inputStream = resource.getInputStream()) {
                byte[] bytes = inputStream.readAllBytes();

                // 5. 设置响应头（处理文件名中文乱码）
                HttpHeaders headers = new HttpHeaders();
                // 对文件名进行URLEncoder编码，避免中文乱码
                String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
                // 设置Content-Disposition，指定下载文件名
                headers.add("Content-Disposition",
                        "attachment; filename*=" + encodedFileName);
                // 设置内容长度（可选，但建议添加）
                headers.setContentLength(bytes.length);
                // 设置文件类型（可选，但建议添加，帮助浏览器识别）
                headers.add(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

                // 6. 返回响应实体（200状态码 + 字节数组 + 响应头）
                return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
            }

        } catch (IOException e) {
            // 处理文件读取异常
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }


    /**
     * 访问文件或目录（支持层级路径）
     * 例如：
     * - 访问目录：http://localhost:8080/files/doc/ → 列出doc目录下的内容
     * - 访问文件：http://localhost:8080/files/image/logo.png → 下载该图片
     */
    @GetMapping("/disk/**")// 匹配所有子路径
    @Operation(summary = "文件服务器")
    public ResponseEntity<?> accessFile() {
        // 1. 获取请求路径（去除前缀/files/）
        String requestUri = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest().getRequestURI();
        String requestPath = requestUri.replaceFirst("/files", "");  // 得到相对路径

        // 2. 映射到本地文件
        File localFile = FileController.getLocalFile("D:/", requestPath);

        // 3. 检查文件是否存在
        if (!localFile.exists()) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body("文件或目录不存在：" + requestPath);
        }

        try {
            // 4. 如果是目录，返回目录列表
            if (localFile.isDirectory()) {
                List<String> fileList = FileController.listDirectory(localFile);
                return ResponseEntity.ok()
                        .header("Content-Type", "text/html;charset=UTF-8")
                        .body(buildDirectoryHtml(requestPath, fileList));  // 返回HTML列表
            }

            // 5. 如果是文件，返回文件下载
            Resource resource = new FileSystemResource(localFile);
            String fileName = URLEncoder.encode(localFile.getName(), StandardCharsets.UTF_8.name());
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION,
                    "attachment; filename*=UTF-8''" + fileName);  // 支持中文文件名

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);

        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("文件操作失败：" + e.getMessage());
        }
    }
    /**
     * 生成目录列表的HTML页面（方便浏览器查看）
     */
    private String buildDirectoryHtml(String currentPath, List<String> fileList) {
        StringBuilder html = new StringBuilder();
        html.append("<html><head><meta charset='UTF-8'><title>目录列表：").append(currentPath).append("</title></head>");
        html.append("<body><h1>目录：").append(currentPath).append("</h1><ul>");

        // 上级目录链接（如果不是根目录）
        if (!currentPath.equals("/")) {
            String parentPath = currentPath.lastIndexOf("/") > 0
                    ? currentPath.substring(0, currentPath.lastIndexOf("/"))
                    : "/";
            html.append("<li><a href='").append(parentPath).append("'>../</a></li>");
        }

        // 列出当前目录下的文件和文件夹
        for (String fileName : fileList) {
            String fileUrl = currentPath.endsWith("/") ? currentPath + fileName : currentPath + "/" + fileName;
            html.append("<li><a href='").append(fileUrl).append("'>").append(fileName).append("</a></li>");
        }
        html.append("</ul></body></html>");
        return html.toString();
    }

    private static final AntPathMatcher pathMatcher = new AntPathMatcher();
    /**
     * 获取本地文件对象（根据根目录和请求路径）
     */
    public static File getLocalFile(String rootPath, String requestPath) {
        // 拼接本地文件路径（处理路径分隔符）
        String fullPath = pathMatcher.combine(rootPath, requestPath);
        return new File(fullPath);
    }
    /**
     * 获取目录下的所有文件/文件夹信息
     */
    public static List<String> listDirectory(File directory) throws IOException {
        if (!directory.isDirectory()) {
            return new ArrayList<>();
        }
        // 列出目录下的所有文件和文件夹，返回相对路径
        return Files.list(Paths.get(directory.getAbsolutePath()))
                .map(path -> {
                    if (path.toFile().isDirectory()) {
                        return path.getFileName() + "/";  // 文件夹末尾加/区分
                    } else {
                        return path.getFileName().toString();
                    }
                })
                .collect(Collectors.toList());
    }
}
